//
// Created by chao.li on 2023/11/10.
//

#ifndef SRC_CIRCLE_QUEUE_H
#define SRC_CIRCLE_QUEUE_H

#include <exception>

template <class TType>
class circle_queue
{
    TType* data = nullptr;
    int max_count;
    int start;
    int end;
    int count;
public:
    circle_queue(int cc)
        : data(new TType[cc]),
          max_count(cc), start(0), end(0), count(0)
    {
    }

    ~circle_queue()
    {
        delete[] data;
        data = nullptr;
    }

    bool is_full() const
    {
        return count == max_count;
    }

    bool is_empty() const
    {
        return count == 0;
    }

    int size() const {
        return count;
    }

    void push_back(const TType& ele)
    {
        if(is_full()){
            // 产生了数据碾压，自动从头部丢失一个数据
            start = (start + 1) % max_count;
            --count;
        }
        data[end] = ele;
        end = (end + 1) % max_count;
        ++count;
    }

    void push_front(const TType& ele)
    {
        if(is_full()){
            // 产生了数据碾压，自动从尾部丢失一个数据
            end = end - 1 < 0 ? max_count : end - 1;
            --count;
        }
        start = start - 1 < 0 ? max_count : start - 1;
        data[start] = ele;
        ++count;
    }

    TType pop_back()
    {
        static_assert(!is_empty());
        end = end - 1 < 0 ? max_count : end - 1;
        --count;
        return data[end];
    }

    TType pop_front()
    {
        static_assert(!is_empty());
        auto& dd = data[start];
        start = (start + 1) % max_count;
        --count;
        return dd;
    }

    int begin_i() const {
        return start;
    }

    int end_i() const {
        return end;
    }

    int next_i(int i, int j = 1) const {
        return (i + j) % max_count;
    }

    int pre_i(int i, int j = 1) const {
        return (i - j) < 0 ? max_count + i - j : i - j;
    }

    TType& operator[] (int i)
    {
        return data[i];
    }

    const TType& operator[] (int i) const
    {
        return data[i];
    }
};

#endif //SRC_CIRCLE_QUEUE_H
